package com.duojuhe.coremodule.system.service.impl;

import com.duojuhe.cache.LoginUserTokenCache;
import com.duojuhe.cache.SystemDictCache;
import com.duojuhe.common.annotation.DataScopeFilter;
import com.duojuhe.common.annotation.KeyLock;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.constant.DataScopeConstants;
import com.duojuhe.common.enums.SystemEnum;
import com.duojuhe.common.enums.user.UserEnum;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.PageResult;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.encryption.md5.MD5Util;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.system.entity.*;
import com.duojuhe.coremodule.system.mapper.*;
import com.duojuhe.coremodule.system.pojo.dto.user.*;
import com.duojuhe.coremodule.system.service.SystemUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class SystemUserServiceImpl extends BaseService implements SystemUserService {
    @Resource
    private LoginUserTokenCache loginUserTokenCache;
    @Resource
    private SystemDictCache systemDictCache;
    @Resource
    private SystemUserMapper systemUserMapper;
    @Resource
    private SystemRoleMapper systemRoleMapper;
    @Resource
    private SystemPostMapper systemPostMapper;
    @Resource
    private SystemDeptMapper systemDeptMapper;
    /**
     * 【分页查询】分页查询用户list
     * @param req
     * @return
     */

    @Override
    @DataScopeFilter
    public ServiceResult<PageResult<List<QuerySystemUserPageRes>>> querySystemUserPageResList(QuerySystemUserPageReq req) {
        //当前登录用户id
        String noUserId = getCurrentLoginUserId();
        PageHelperUtil.orderByAndStartPage(req, "createTime desc, userId desc");
        List<QuerySystemUserPageRes> list = systemUserMapper.querySystemUserPageResList(req,noUserId);
        list.forEach(this::setHandleSystemUserDictNameColor);
        return PageHelperUtil.returnServiceResult(req,list);
    }

    /**
     * 【分页查询】分页选择系统用户list
     * @param req
     * @return
     */
    @DataScopeFilter(dataScope = DataScopeConstants.TENANT_ALL_DATA)
    public ServiceResult<PageResult<List<QuerySelectSystemUserRes>>> querySelectSystemUserResList(QuerySelectSystemUserReq req) {
        //当前登录用户id
        String noUserId = getCurrentLoginUserId();
        PageHelperUtil.orderByAndStartPage(req, "createTime desc, userId desc");
        List<QuerySelectSystemUserRes> list = systemUserMapper.querySelectSystemUserResList(req,noUserId);
        list.forEach(this::setHandleSystemUserDictNameColor);
        return PageHelperUtil.returnServiceResult(req,list);
    }


    /**
     * 【根据ID查询详情】根据用户Id查询用户详情
     * @param req
     * @return
     */
    @Override
    public ServiceResult<QuerySystemUserRes> querySystemUserResByUserId(SystemUserIdReq req) {
        String userId = req.getUserId();
        QuerySystemUserRes res = systemUserMapper.querySystemUserResByUserId(userId);
        if (res==null || UserEnum.USER_TYPE.SUPER_ADMIN.getKey().equals(res.getUserTypeCode())){
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        setHandleSystemUserDictNameColor(res);
        return ServiceResult.ok(res);
    }


    /**
     * 【保存】用户信息
     * @param req
     * @return
     */
    @Override
    public ServiceResult saveSystemUser(SaveSystemUserReq req) {
        //检查登录名是否存在
        isExistUserLoginName(req.getLoginName());
        //校验手机号码是否已经存在
        isExistUserMobileNumber(req.getMobileNumber());
        //获取部门
        SystemDept systemDept = getSystemDeptByDeptId(req.getCreateDeptId());
        //检查角色
        checkExistRole(req.getRoleId(),systemDept.getTenantId());
        //检查岗位
        checkExistPost(req.getPostId(),systemDept.getTenantId());
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //用户所属模块
        String userModuleCode = userTokenInfoVo.getUserModuleCode();
        //当前时间
        Date date = new Date();
        //用户id
        String userId = UUIDUtils.getUUID32();
        //密码
        String newPwd = MD5Util.getMD532(MD5Util.getMD532(req.getPassword()));
        SystemUser systemUser = new SystemUser();
        systemUser.setUserId(userId);
        systemUser.setUserNumber(UUIDUtils.getSequenceNo());
        systemUser.setLoginName(req.getLoginName());
        systemUser.setMobileNumber(req.getMobileNumber());
        systemUser.setRoleId(req.getRoleId());
        systemUser.setCreateDeptId(systemDept.getDeptId());
        systemUser.setTenantId(systemDept.getTenantId());
        systemUser.setPostId(req.getPostId());
        systemUser.setStatusCode(req.getStatusCode());
        systemUser.setPassword(newPwd);
        systemUser.setRealName(req.getRealName());
        systemUser.setModuleCode(StringUtils.isBlank(userModuleCode)?SystemEnum.MODULE.SYSTEM_MODULE.getKey():userModuleCode);
        systemUser.setUserTypeCode(UserEnum.USER_TYPE.DEPT_USER.getKey());
        systemUser.setCreateUserId(userTokenInfoVo.getUserId());
        systemUser.setUpdateUserId(userTokenInfoVo.getUserId());
        systemUser.setCreateTime(date);
        systemUser.setUpdateTime(date);
        systemUser.setGenderCode(req.getGenderCode());
        systemUserMapper.insertSelective(systemUser);
        return ServiceResult.ok(userId);
    }

    /**
     * 【修改】用户信息
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "userId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult updateSystemUser(UpdateSystemUserReq req) {
        //检查用户id
        SystemUser systemUserOld = checkSystemUserByUserId(req.getUserId());
        //检查角色
        checkExistRole(req.getRoleId(),systemUserOld.getTenantId());
        //检查岗位
        checkExistPost(req.getPostId(),systemUserOld.getTenantId());
        //检查手机号码是否存在
        if (!req.getMobileNumber().equals(systemUserOld.getMobileNumber())){
            isExistUserMobileNumber(req.getMobileNumber());
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //当前时间
        Date date = new Date();
        SystemUser systemUser = new SystemUser();
        systemUser.setUserId(req.getUserId());
        systemUser.setRoleId(req.getRoleId());
        systemUser.setMobileNumber(req.getMobileNumber());
        systemUser.setStatusCode(req.getStatusCode());
        systemUser.setPostId(req.getPostId());
        systemUser.setRealName(req.getRealName());
        systemUser.setUpdateTime(date);
        systemUser.setUpdateUserId(userTokenInfoVo.getUserId());
        systemUser.setGenderCode(req.getGenderCode());
        if (!StringUtils.isEmpty(req.getPassword())) {
            systemUser.setPassword(MD5Util.getMD532(MD5Util.getMD532(req.getPassword())));
        }
        systemUserMapper.updateByPrimaryKeySelective(systemUser);
        //用户信息修改了，强制踢出刚用户的所有在线会话
        loginUserTokenCache.kickOutOnlineUserByUserId(req.getUserId());
        return ServiceResult.ok(req.getUserId());
    }

    /**
     * 【删除】根据用户id删除用户
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "userId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult deleteSystemUserByUserId(SystemUserIdReq req) {
        String userId = req.getUserId();
        //检查用户id
        checkSystemUserByUserId(userId);
        if (loginUserTokenCache.checkUserIsOnline(userId)) {
            return ServiceResult.fail(ErrorCodes.USER_ONLINE);
        }
        //删除用户
        systemUserMapper.deleteByPrimaryKey(userId);
        return ServiceResult.ok(userId);
    }


    /**
     * 【改变状态】根据用户id改变用户状态
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "userId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult updateSystemUserStatusByUserId(SystemUserIdReq req) {
        String userId = req.getUserId();
        //检查用户id
        SystemUser systemUserOld = checkSystemUserByUserId(userId);
        //默认用户状态
        String status = SystemEnum.STATUS.FORBID.getKey();
        if (status.equals(systemUserOld.getStatusCode())){
            status = SystemEnum.STATUS.NORMAL.getKey();
        }
        SystemUser systemUser = new SystemUser();
        systemUser.setUserId(userId);
        systemUser.setStatusCode(status);
        systemUserMapper.updateByPrimaryKeySelective(systemUser);
        //用户状态被禁用了，强制踢出刚用户的所有在线会话
        if (status.equals(SystemEnum.STATUS.FORBID.getKey())){
            loginUserTokenCache.kickOutOnlineUserByUserId(req.getUserId());
        }
        return ServiceResult.ok(userId);
    }

    /**
     * 【重置密码】根据用户id重置密码
     * @param req
     * @return
     */
    @KeyLock(lockKeyParts = "userId")
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ServiceResult resetSystemUserPassword(ResetSystemUserPasswordReq req) {
        //检查用户id
        checkSystemUserByUserId(req.getUserId());
        SystemUser systemUser = new SystemUser();
        systemUser.setUserId(req.getUserId());
        systemUser.setPassword(MD5Util.getMD532(MD5Util.getMD532(req.getPassword())));
        systemUserMapper.updateByPrimaryKeySelective(systemUser);
        //密码修改了，强制踢出该用户的所有在线会话
        loginUserTokenCache.kickOutOnlineUserByUserId(req.getUserId());
        return ServiceResult.ok(req.getUserId());
    }



    /*====================================私有方法beg==============================================**/

    /**
     * 根据用户id判断检查用户
     * @param userId
     */
    private SystemUser checkSystemUserByUserId(String userId){
        if (StringUtils.isBlank(userId)){
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        SystemUser systemUser = systemUserMapper.selectByPrimaryKey(userId);
        if (systemUser == null) {
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        //用户类型
        String userTypeCode = systemUser.getUserTypeCode();
        if (UserEnum.USER_TYPE.SUPER_ADMIN.getKey().equals(userTypeCode)
                ||UserEnum.USER_TYPE.TENANT_ADMIN.getKey().equals(userTypeCode)) {
            throw new DuoJuHeException(ErrorCodes.PARAM_ERROR);
        }
        return systemUser;
    }

    /**
     * 判断登录名是否存在
     */
    private void isExistUserLoginName(String loginName) {
        if (StringUtils.isBlank(loginName)){
            throw new DuoJuHeException(ErrorCodes.USER_LOGIN_NAME_EXIST);
        }
        SystemUser systemUser = systemUserMapper.querySystemUserByLoginName(loginName);
        if (systemUser != null) {
            throw new DuoJuHeException(ErrorCodes.USER_LOGIN_NAME_EXIST);
        }
    }


    /**
     * 判断手机号码是否存在
     */
    private void isExistUserMobileNumber(String mobileNumber) {
        if (StringUtils.isBlank(mobileNumber)){
            throw new DuoJuHeException(ErrorCodes.MOBILE_NUMBER_EXIST);
        }
        SystemUser systemUser = systemUserMapper.querySystemUserByMobileNumber(mobileNumber);
        if (systemUser != null) {
            throw new DuoJuHeException(ErrorCodes.MOBILE_NUMBER_EXIST);
        }
    }

    /**
     * 检查角色
     */
    private void checkExistRole(String roleId,String tenantId) {
        if (StringUtils.isBlank(roleId)||StringUtils.isBlank(tenantId)){
            throw new DuoJuHeException(ErrorCodes.ROLE_NOT_EXIST);
        }
        SystemRole systemRole = systemRoleMapper.selectByPrimaryKey(roleId);
        if (systemRole == null || !tenantId.equals(systemRole.getTenantId())) {
            throw new DuoJuHeException(ErrorCodes.ROLE_NOT_EXIST);
        }
        if (!SystemEnum.STATUS.NORMAL.getKey().equals(systemRole.getStatusCode())) {
            throw new DuoJuHeException(ErrorCodes.ROLE_FORBID);
        }
    }

    /**
     * 获取部门
     */
    private SystemDept getSystemDeptByDeptId(String deptId) {
        if (StringUtils.isBlank(deptId)){
            throw new DuoJuHeException(ErrorCodes.DEPT_NOT_EXIST);
        }
        SystemDept systemDept = systemDeptMapper.selectByPrimaryKey(deptId);
        if (systemDept == null) {
            throw new DuoJuHeException(ErrorCodes.DEPT_NOT_EXIST);
        }
        if (StringUtils.isBlank(systemDept.getTenantId())){
            throw new DuoJuHeException(ErrorCodes.DEPT_NOT_EXIST);
        }
        return systemDept;
    }


    /**
     * 检查岗位
     */
    private void checkExistPost(String postId,String tenantId) {
        if (StringUtils.isBlank(postId)||StringUtils.isBlank(tenantId)){
            throw new DuoJuHeException(ErrorCodes.POST_NOT_EXIST);
        }
        SystemPost systemPost = systemPostMapper.selectByPrimaryKey(postId);
        if (systemPost == null || !tenantId.equals(systemPost.getTenantId())) {
            throw new DuoJuHeException(ErrorCodes.POST_NOT_EXIST);
        }
    }


    /**
     * 处理返回值的数据字典
     * @param res
     */
    private void setHandleSystemUserDictNameColor(HandleSystemUserDictNameColorRes res) {
        if (res==null){
            return;
        }
        SystemDict dictStatus = systemDictCache.getSystemDictByDictCode(res.getStatusCode());
        res.setStatusName(dictStatus.getDictName());
        res.setStatusColor(dictStatus.getDictColor());

        SystemDict userType = systemDictCache.getSystemDictByDictCode(res.getUserTypeCode());
        res.setUserTypeName(userType.getDictName());
        res.setUserTypeColor(userType.getDictColor());

        SystemDict genderCode = systemDictCache.getSystemDictByDictCode(res.getGenderCode());
        res.setGenderName(genderCode.getDictName());
        res.setGenderColor(genderCode.getDictColor());
    }
}
